/**
 * Copyright 2015-2016 eyaomall.cn
 * All rights reserved.
 *
 * @project
 * @author jackey
 * @version 1.0
 * @date 2016-01-06
 */
package com.eyaomall.wxmall.controller;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.eyaomall.wxmall.common.error.BECode;
import com.eyaomall.wxmall.common.helper.MemberHelper;
import com.eyaomall.wxmall.common.util.DateUtils;
import com.eyaomall.wxmall.model.po.Address;
import com.eyaomall.wxmall.model.po.Coupon;
import com.eyaomall.wxmall.model.po.Goods;
import com.eyaomall.wxmall.model.po.Logistics;
import com.eyaomall.wxmall.model.po.Order;
import com.eyaomall.wxmall.model.po.OrderGoods;
import com.eyaomall.wxmall.model.po.Shop;
import com.eyaomall.wxmall.model.pojo.ReqGoods;
import com.eyaomall.wxmall.model.pojo.ReqPrepareOrder;
import com.eyaomall.wxmall.model.pojo.RespOrder;
import com.eyaomall.wxmall.model.pojo.RespOrderGoods;
import com.eyaomall.wxmall.model.pojo.RespPrepareGoods;
import com.eyaomall.wxmall.model.vo.CouponVO;
import com.eyaomall.wxmall.model.vo.DiscountRecordVO;
import com.eyaomall.wxmall.model.vo.TranspsortVO;
import com.eyaomall.wxmall.service.AddressService;
import com.eyaomall.wxmall.service.CouponService;
import com.eyaomall.wxmall.service.DiscountGoodsService;
import com.eyaomall.wxmall.service.GoodsService;
import com.eyaomall.wxmall.service.GoodsTransportService;
import com.eyaomall.wxmall.service.LogisticsService;
import com.eyaomall.wxmall.service.OrderService;
import com.eyaomall.wxmall.service.ShopService;
import com.github.pagehelper.StringUtil;
import com.lycheeframework.core.cmp.api.http.GsnData;
import com.lycheeframework.core.cmp.api.http.GsnResponse;
import com.lycheeframework.core.cmp.kit.PageHTTPObject;
import com.lycheeframework.core.cmp.kit.Pages;
import com.lycheeframework.core.common.util.JSONUtil;
import com.lycheeframework.core.exception.ErrorCodeException;

/**
 * 订单controller
 * 
 * @author pro
 *
 */
@Controller
@RequestMapping("order")
public class OrderController {

	@Autowired
	private OrderService orderService;

	@Autowired
	private GoodsService goodsService;

	@Autowired
	private AddressService addressService;

	@Autowired
	private ShopService shopService;

	@Autowired
	private GoodsTransportService transportService;

	@Autowired
	private DiscountGoodsService discountGoodsService;

	@Autowired
	private CouponService couponService;

	@Autowired
	private LogisticsService logisticsService;

	private static Logger LOG = LoggerFactory.getLogger(OrderController.class);

	/**
	 * 订单首页
	 * 
	 * @return
	 */
	@RequestMapping("index")
	public String index(String status, Map<String, Object> data) {
		data.put("status", status);

		return "order/index";
	}

	/**
	 * 订单详情
	 * 
	 * @return
	 */
	@RequestMapping("detail")
	public String detail(Integer id, Map<String, Object> data) throws Exception {
		// 查询订单详情
		Order order = orderService.queryById(id);

		// 查询订单产品列表
		List<OrderGoods> orderGoodsList = orderService.listOrderGoods(id);

		// 通过orderId查询物流表如果有数据返回1无数据返回0
		Logistics logis = (Logistics) logisticsService.queryByOrderId(id);
		if (logis == null) {
			data.put("getLogis", 1);
		} else {
			data.put("getLogis", 0);
		}

		// 去除敏感ID，只返回页面所需数据
		RespOrder respOrder = new RespOrder();
		List<RespOrderGoods> list = new ArrayList<RespOrderGoods>();
		PropertyUtils.copyProperties(respOrder, order);
		List<Map<String, Object>> jsonList = new ArrayList<Map<String, Object>>();

		for (OrderGoods orderGoods : orderGoodsList) {
			RespOrderGoods respGoods = new RespOrderGoods();
			PropertyUtils.copyProperties(respGoods, orderGoods);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("goodsId", orderGoods.getGoodsId());
			map.put("num", orderGoods.getNum());

			jsonList.add(map);

			list.add(respGoods);
		}

		respOrder.setOrderGoods(list);
		Shop shop = shopService.queryById(MemberHelper.getShopId());
		data.put("shop", shop);
		data.put("json", JSONUtil.toString(jsonList));
		data.put("order", respOrder);
		long countdowntime = 0;
		if ("0".equals(order.getStatus())) {

			countdowntime = DateUtils.dateAfterMin(order.getGmtCreate(), 60).getTime() - new Date().getTime();
		}
		if ("2".equals(order.getStatus())) {
			countdowntime = DateUtils.dateAfterDays(order.getGmtModified(), 7).getTime() - new Date().getTime();
		}
		data.put("countdowntime", countdowntime);

		return "order/detail";
	}

	/**
	 * 设置为已收货
	 * 
	 * @param orderId
	 * @return
	 */
	@RequestMapping("set_receive")
	public @ResponseBody GsnData setReceive(Integer orderId) {
		if (orderId == null || orderId <= 0)
			throw new ErrorCodeException(BECode.order_4000001);

		Order order = orderService.queryById(orderId);
		if (order == null)
			throw new ErrorCodeException(BECode.order_4000001);

		if (!"2".equalsIgnoreCase(order.getStatus()))
			throw new ErrorCodeException(BECode.order_4000004);

		return GsnResponse.toData(orderService.setReceive(order));
	}

	/**
	 * 设置为关闭
	 * 
	 * @param orderId
	 * @return
	 */
	@RequestMapping("set_cancel")
	public @ResponseBody GsnData setCancel(Integer orderId) {
		if (orderId == null || orderId <= 0)
			throw new ErrorCodeException(BECode.order_4000001);

		Order order = orderService.queryById(orderId);
		if (order == null)
			throw new ErrorCodeException(BECode.order_4000001);

		if (!"0".equalsIgnoreCase(order.getStatus()))
			throw new ErrorCodeException(BECode.order_4000004);
		// 如果是未支付取消订单，状态为关闭，如果已支付订单状态为待退款
		order.setStatus("4");
		return GsnResponse.toData(orderService.update(order));
	}

	/**
	 * 分页查询我的订单数据
	 * 
	 * @param orderVO
	 * @param httpObj
	 * @return
	 */
	@RequestMapping("page_data")
	public @ResponseBody GsnData page(Order orderVO, PageHTTPObject httpObj) {
		// 分页查询我的订单数据
		orderVO.setMemberId(MemberHelper.getId());
		Pages<List<Order>> pages = orderService.page(orderVO, httpObj);
		List<Order> orderList = pages.getRows();
		List<RespOrder> list = new ArrayList<RespOrder>();

		Shop shop = shopService.queryById(MemberHelper.getShopId());

		try {
			// 查询我的订单产品信息，并晒去敏感的ID
			for (Order order : orderList) {
				RespOrder respOrder = new RespOrder();
				PropertyUtils.copyProperties(respOrder, order);
				respOrder.setShopName(shop.getCompanyName());

				List<RespOrderGoods> dataList = new ArrayList<RespOrderGoods>();
				List<OrderGoods> orderGoodsList = orderService.listOrderGoods(order.getId());
				for (OrderGoods orderGoods : orderGoodsList) {
					RespOrderGoods respOrderGoods = new RespOrderGoods();
					PropertyUtils.copyProperties(respOrderGoods, orderGoods);

					dataList.add(respOrderGoods);
				}
				respOrder.setOrderGoods(dataList);

				list.add(respOrder);
			}

		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}

		Pages<List<RespOrder>> orderPages = new Pages<List<RespOrder>>();
		orderPages.setTotal(pages.getTotal());
		orderPages.setRows(list);

		return GsnResponse.toData(orderPages);
	}

	/**
	 * 新增订单 [{"id":1,"num:1},{"id":2,"num":2}]
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@RequestMapping("add")
	public @ResponseBody GsnData add(String json, Integer aId, Integer cId) throws Exception {
		if (StringUtil.isEmpty(json))
			throw new ErrorCodeException(BECode.goods_200001);
		json = URLDecoder.decode(json, "utf-8");

		if (aId == null || aId <= 0)
			throw new ErrorCodeException(BECode.address_300001);

		// 查询收货地址
		Address address = addressService.queryById(aId);
		if (address == null)
			throw new ErrorCodeException(BECode.address_300002);

		List<Map<String, Integer>> params = (List<Map<String, Integer>>) JSONUtil.toList(json);
		if (params == null || params.isEmpty()) {
			throw new ErrorCodeException(BECode.goods_200001);
		}

		StringBuilder idsBuilder = new StringBuilder();
		Map<Integer, Integer> numMap = new HashMap<Integer, Integer>();
		for (Map map : params) {
			Integer id = (Integer) map.get("id");
			Integer num = (Integer) map.get("num");
			idsBuilder.append(id);
			idsBuilder.append(",");

			numMap.put(id, num);
		}

		String ids = idsBuilder.substring(0, idsBuilder.length() - 1);
		List<Goods> goodsList = goodsService.list(ids);

		List<ReqGoods> list = new ArrayList<ReqGoods>();

		for (Goods goods : goodsList) {
			// 校验已删除或者下线
			if ("n".equalsIgnoreCase(goods.getIsPublish()) || "y".equalsIgnoreCase(goods.getIsDeleted())) {
				throw new ErrorCodeException(BECode.pay_5000003);
			}

			// 校验库存
			Integer num = numMap.get(goods.getId());
			if (num > goods.getInventory()) {
				throw new ErrorCodeException(BECode.pay_5000004);
			}

			ReqGoods reqGoods = new ReqGoods();
			try {
				PropertyUtils.copyProperties(reqGoods, goods);
			} catch (Exception e) {
				LOG.error(e.getMessage(), e);
			}
			reqGoods.setNum(num);

			list.add(reqGoods);
		}

		Integer orderId = orderService.create(list, address.getCityId(), address, cId);
		return GsnResponse.toData(orderId);
	}

	/**
	 * 订单确认页
	 * 
	 * @param json,格式为数组[{"goodsId":1,"num":1}，{"goodsId":2,"num":1}]
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping("confirm2")
	public String prepare(String json, Integer aId, Map<String, Object> data) throws Exception {
		if (StringUtil.isEmpty(json))
			throw new ErrorCodeException(BECode.goods_200001);
		json = URLDecoder.decode(json, "utf-8");
		List<ReqPrepareOrder> infoList = (List<ReqPrepareOrder>) JSONUtil.toList(json, ReqPrepareOrder.class);
		if (infoList == null || infoList.isEmpty())
			throw new ErrorCodeException(BECode.goods_200002);

		// 拼接goodsId
		StringBuilder goodsIdStr = new StringBuilder();
		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		for (ReqPrepareOrder order : infoList) {
			goodsIdStr.append(order.getGoodsId());
			goodsIdStr.append(",");

			map.put(order.getGoodsId(), order.getNum());
		}
		String goodsId = goodsIdStr.substring(0, goodsIdStr.length() - 1);
		List<Goods> goodsList = goodsService.list(goodsId);
		List<RespPrepareGoods> list = new ArrayList<RespPrepareGoods>();

		BigDecimal totalAmount = new BigDecimal("0");

		try {
			for (Goods goods : goodsList) {
				RespPrepareGoods pGoods = new RespPrepareGoods();
				PropertyUtils.copyProperties(pGoods, goods);

				pGoods.setNum(map.get(pGoods.getId()));
				list.add(pGoods);

				BigDecimal amount = goods.getPrice().multiply(new BigDecimal(pGoods.getNum()));
				totalAmount = totalAmount.add(amount);
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}

		if (aId == null || aId <= 0) {
			// 获取默认收货地址，如果没有取第一条收货地址
			Address address = addressService.queryDefaultByMemberId(MemberHelper.getId());
			if (address == null) {
				List<Address> addressList = addressService.list(MemberHelper.getId());
				if (addressList != null && !addressList.isEmpty()) {
					data.put("address", addressList.get(0));
				}
			} else {
				data.put("address", address);
			}
		} else {
			Address address = addressService.queryById(aId);
			data.put("address", address);
		}

		Map<String, Boolean> noTrans = new HashMap<String, Boolean>();
		if (data.get("address") != null) {
			BigDecimal transportAmount = calcTransportAmount(((Address) data.get("address")).getCityId(), goodsId,
					goodsList, noTrans);
			data.put("transport", transportAmount);

			totalAmount = totalAmount.add(transportAmount);
			data.put("amount", totalAmount);
		}

		Shop shop = shopService.queryById(MemberHelper.getShopId());

		data.put("shop", shop);
		data.put("dataList", list);
		data.put("json", URLEncoder.encode(json, "UTF-8"));
		return "order/confirm";
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("confirm")
	public String prepare2(String json, Integer aId, Map<String, Object> data) throws Exception {
		if (StringUtil.isEmpty(json))
			throw new ErrorCodeException(BECode.goods_200001);
		json = URLDecoder.decode(json, "utf-8");
		List<ReqPrepareOrder> infoList = (List<ReqPrepareOrder>) JSONUtil.toList(json, ReqPrepareOrder.class);
		if (infoList == null || infoList.isEmpty())
			throw new ErrorCodeException(BECode.goods_200002);

		// 拼接goodsId
		StringBuilder goodsIdStr = new StringBuilder();
		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		for (ReqPrepareOrder order : infoList) {
			goodsIdStr.append(order.getGoodsId());
			goodsIdStr.append(",");

			map.put(order.getGoodsId(), order.getNum());
		}
		String goodsId = goodsIdStr.substring(0, goodsIdStr.length() - 1);
		List<Goods> goodsList = goodsService.list(goodsId);
		List<RespPrepareGoods> list = new ArrayList<RespPrepareGoods>();

		BigDecimal totalAmount = new BigDecimal("0");

		try {
			for (Goods goods : goodsList) {
				RespPrepareGoods pGoods = new RespPrepareGoods();
				PropertyUtils.copyProperties(pGoods, goods);

				pGoods.setNum(map.get(pGoods.getId()));
				list.add(pGoods);

				BigDecimal amount = goods.getPrice().multiply(new BigDecimal(pGoods.getNum()));
				totalAmount = totalAmount.add(amount);
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}

		if (aId == null || aId <= 0) {
			// 获取默认收货地址，如果没有取第一条收货地址
			Address address = addressService.queryDefaultByMemberId(MemberHelper.getId());
			if (address == null) {
				List<Address> addressList = addressService.list(MemberHelper.getId());
				if (addressList != null && !addressList.isEmpty()) {
					data.put("address", addressList.get(0));
				}
			} else {
				data.put("address", address);
			}
		} else {
			Address address = addressService.queryById(aId);
			data.put("address", address);
		}
		Map<String, Boolean> noTrans = new HashMap<String, Boolean>();
		if (data.get("address") != null) {
			BigDecimal transportAmount = calcTransportAmount(((Address) data.get("address")).getCityId(), goodsId,
					goodsList, noTrans);
			data.put("transport", transportAmount);

			totalAmount = totalAmount.add(transportAmount);
			data.put("amount", totalAmount);
		}

		int allowGoods = list.size();

		for (int i = 0; i < list.size(); i++) {
			RespPrepareGoods res = list.get(i);
			Boolean flag = noTrans.get(res.getId() + "");
			System.out.println(res.getNum());
			if ("y".equals(res.getIsDeleted()) || "n".equals(res.getIsPublish()) || res.getInventory() < res.getNum()) {
				flag = false;
			}
			if (flag != null && flag) {
				res.setUniteTransport(new BigDecimal("1"));
			} else {
				res.setUniteTransport(new BigDecimal("0"));
				allowGoods--;
			}
			list.set(i, res);
		}

		Shop shop = shopService.queryById(MemberHelper.getShopId());
		data.put("shop", shop);
		data.put("dataList", list);
		data.put("allowGoods", allowGoods);
		data.put("noAllowGoods", list.size() - allowGoods);
		data.put("json", URLEncoder.encode(json, "UTF-8"));

		BigDecimal decimal = new BigDecimal("0");
		StringBuilder builder = new StringBuilder();
		for (RespPrepareGoods goods : list) {
			BigDecimal dd = goods.getPrice().multiply(new BigDecimal(goods.getNum()));

			decimal = decimal.add(dd);
			builder.append(goods.getId());
			builder.append(",");
		}

		CouponVO coupon = new CouponVO();
		coupon.setAmount(decimal.doubleValue());
		coupon.setGoodsIds(builder.toString());
		List<Coupon> couponList = couponService.listMyCoupons(coupon);
		data.put("cList", couponList);
		data.put("tAmount", decimal);

		return "order/confirm";
	}

	/**
	 * 计算最大运费
	 * 
	 * @param cityId
	 * @param goodsIds
	 * @param goodsList
	 * @return
	 */
	private BigDecimal calcTransportAmount(Integer cityId, String goodsIds, List<Goods> goodsList,
			Map<String, Boolean> map) {
		List<BigDecimal> transportAmount = new ArrayList<BigDecimal>();
		for (Goods goods : goodsList) {
			if (goods.getUniteTransport() != null) {
				transportAmount.add(goods.getUniteTransport());
				map.put(goods.getId() + "", true);
			}
		}

		List<TranspsortVO> transportList = transportService.listTransport(goodsIds, cityId);
		for (TranspsortVO transport : transportList) {
			transportAmount.add(transport.getAmount());
			map.put(transport.getGoodsId() + "", true);
		}

		Collections.sort(transportAmount);
		Collections.reverse(transportAmount);
		return transportAmount.isEmpty() ? new BigDecimal("0") : transportAmount.get(0);
	}

	/**
	 * 砍价活动订单确认页面
	 * 
	 * @param discountId
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@RequestMapping("discount_confirm")
	public String discountConfirm(Integer aId, Integer discountId, Map<String, Object> data)
			throws UnsupportedEncodingException {
		if (discountId == null || discountId <= 0)
			throw new ErrorCodeException(BECode.order_4000002);

		DiscountRecordVO recordVO = discountGoodsService.queryByMemberDiscountId(discountId);

		Goods goods = goodsService.query(recordVO.getGoodsId());
		BigDecimal totalAmount = recordVO.getPrice();

		List<Goods> list = new ArrayList<Goods>();
		list.add(goods);

		if (aId == null || aId <= 0) {
			// 获取默认收货地址，如果没有取第一条收货地址
			Address address = addressService.queryDefaultByMemberId(MemberHelper.getId());
			if (address == null) {
				List<Address> addressList = addressService.list(MemberHelper.getId());
				if (addressList != null && !addressList.isEmpty()) {
					data.put("address", addressList.get(0));
				}
			} else {
				data.put("address", address);
			}
		} else {
			Address address = addressService.queryById(aId);
			data.put("address", address);
		}

		Map<String, Boolean> noTrans = new HashMap<String, Boolean>();
		if (data.get("address") != null) {
			BigDecimal transportAmount = calcTransportAmount(((Address) data.get("address")).getCityId(),
					String.valueOf(goods.getId()), list, noTrans);
			data.put("transport", transportAmount);

			totalAmount = totalAmount.add(transportAmount);
			data.put("amount", totalAmount);
		}

		data.put("goodsVO", goods);
		data.put("recordVO", recordVO);

		BigDecimal dd = goods.getPrice();

		CouponVO coupon = new CouponVO();
		coupon.setAmount(dd.doubleValue());
		List<Coupon> couponList = couponService.listMyCoupons(coupon);
		data.put("cList", couponList);
		data.put("tAmount", dd);

		return "order/discount_confirm";
	}

	/**
	 * 新增砍价订单
	 * 
	 * @param discountId
	 * @param aId
	 * @return
	 */
	@RequestMapping("add_discount")
	public @ResponseBody GsnData addDiscountOrder(Integer discountId, Integer aId, Integer cId) {
		if (discountId == null || discountId <= 0)
			throw new ErrorCodeException(BECode.order_4000002);

		if (aId == null || aId <= 0)
			throw new ErrorCodeException(BECode.address_300001);

		DiscountRecordVO recordVO = discountGoodsService.queryByMemberDiscountId(discountId);
		Goods goods = goodsService.query(recordVO.getGoodsId());

		if ("n".equalsIgnoreCase(goods.getIsPublish()) || "y".equalsIgnoreCase(goods.getIsDeleted()))
			throw new ErrorCodeException(BECode.pay_5000003);

		if (recordVO.getNum() > goods.getInventory()) {
			throw new ErrorCodeException(BECode.pay_5000004);
		}

		Address address = addressService.queryById(aId);

		return GsnResponse.toData(orderService.createDisCountOrder(discountId, goods, address, cId));
	}

	/**
	 * 获取确认订单数据
	 * 
	 * @param orderId
	 * @return
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 */
	@RequestMapping("get_confirm_data")
	public @ResponseBody GsnData getConfirmData(Integer orderId) throws Exception {
		if (orderId == null || orderId <= 0)
			throw new ErrorCodeException(BECode.order_4000001);

		// 查询订单产品列表
		List<OrderGoods> orderGoodsList = orderService.listOrderGoods(orderId);

		List<Map<String, Object>> jsonList = new ArrayList<Map<String, Object>>();

		for (OrderGoods orderGoods : orderGoodsList) {
			Goods goods = goodsService.query(orderGoods.getGoodsId());
			if (goods == null)
				throw new ErrorCodeException(BECode.goods_200003);

			RespOrderGoods respGoods = new RespOrderGoods();
			PropertyUtils.copyProperties(respGoods, orderGoods);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("goodsId", orderGoods.getGoodsId());
			map.put("num", orderGoods.getNum());

			jsonList.add(map);

		}

		return GsnResponse.toData(JSONUtil.toString(jsonList));
	}

	/**
	 * 选择我的地址
	 * 
	 * @param json
	 * @return
	 */
	@RequestMapping("select_address")
	public String selectAddress(String json, String redirectUrl, Map<String, Object> data) {
		Integer memberId = MemberHelper.getId();

		data.put("json", json);
		data.put("redirectUrl", redirectUrl);
		data.put("aList", addressService.list(memberId));
		return "order/selectAddress";
	}

}
